package com.jf.cloud.service.sysmanager.common.db;

import static com.jf.cloud.service.sysmanager.common.db.FindType.FIND_FLAG;
import static com.jf.cloud.service.sysmanager.common.db.FindType.LIKE_OR_FLAG;
import static com.jf.cloud.service.sysmanager.common.db.FindType.OR_FLAG;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;


/**
 * TODO  SQL 语句解析
 */
@SuppressWarnings("all")
public class SqlParse {
	private static final long serialVersionUID = 1L;
	private static Log log = LogFactory.getLog(SqlParse.class);
	
	private static final String REGEX_SQL_KEYWORD = "('.,)|(;)|(:')|(:--)|(\\b(select|update|delete|insert|trancate|char|into|substr|ascii|declare|exec|count|master|into|drop|execute)\\b)";
	private static Pattern pattern = Pattern.compile(REGEX_SQL_KEYWORD, Pattern.CASE_INSENSITIVE);
	/**
     * TODO  解析 page内参数
     */
	public static String parse(Map<String, Object> whereMap, List<Object> param, Query query) {
		query.init(); // 初始化 参数
		return createSql(whereMap, param);
	}
	
	/**
	 * TODO  解析 Query 内参数
	 */
	public static String parseQuery(Map<String, Object> whereMap, List<Object> param) {
		 return createSql(whereMap, param);
	}
	
	/**
	 * 统一解析 SQL 语句
	 * 1.0 SQL 过滤
	 * 2.0 优化字符串分解效率 common.StringUtil
	 * @author ouyang 创建时间：2012-03-13 01:14:44
	 */
	protected static String createSql(Map<String, Object> whereMap,List<Object> param) {
		StringBuffer sql = new StringBuffer(100); // 最后生成的SQL
		try {
			String columnName = ""; //  解析字段名
			String columnNamePrefix = "";// 解析前缀
			boolean flag_add_value=true;  //  对于 not null等 取值为 false 不需要加入参数值
			String flag_like=""; // like 查询的分类  all right left
			
			Map<String, String> findOR = new HashMap<String, String>(); //or 查询的分组查询
			   // 组名 ，(a=b and b=c and b=c)
			Map<String, String> findORLike = new HashMap<String, String>(); //or 查询的分组查询
			   // 组名 ，(a like '?' and b like '?' and b like '?')
			
			if(whereMap==null || whereMap.isEmpty()){ 
				log.info("没有查询条件，无法组装 SQL 语句------------------");
				param = Collections.EMPTY_LIST;
				return "";
			} 
			//修改时 备注 FindType.LIKE key 要取值 为带下划线的 FindType.LIKE_
			for (Map.Entry<String, Object> e:whereMap.entrySet()) { 
				if(e.getKey()!=null && e.getValue()!=null && e.getValue().toString().length()>0  && !e.getKey().startsWith(FindType.NO_CONTANT)){
					flag_like=""; // 是否为like 查询
					flag_add_value=true; // 需要添加参数值
					if(e.getKey().contains(FIND_FLAG)){ // 特殊查询
						columnName = StringUtils.split(e.getKey(),FIND_FLAG)[1];
						columnNamePrefix = StringUtils.split(e.getKey(),FIND_FLAG)[0]+FIND_FLAG;  // 拼接前缀
						if(FindType.LIKE_.equals(columnNamePrefix)){
							flag_like = FindType.ALL;
							sql.append(" AND "+columnName+" LIKE ? ");
						}else if(FindType.LIKE_LEFT_.equals(columnNamePrefix)){ //  左 like
							flag_like = FindType.LEFT;
							sql.append(" AND "+columnName+" LIKE ? ");
						}else if(FindType.LIKE_RIGHT_.equals(columnNamePrefix)){// 右 like
							flag_like = FindType.RIGHT;
							sql.append(" AND "+columnName+" LIKE ? ");
						}else if(FindType.IN_.equals(columnNamePrefix)){ //解决 jdbc bug in 不用 ？  处理
							sql.append(" AND "+columnName+" IN ( "+e.getValue()+" ) ");
							flag_add_value = false;
						}else if(FindType.IS_NULL_.equals(columnNamePrefix)){
							sql.append(" AND "+columnName+" IS NULL ");
							flag_add_value = false;
						}else if (FindType.NOT_NULL_.equals(columnNamePrefix)) {
							sql.append(" AND "+columnName+" IS NOT NULL");
							flag_add_value = false; // 不为 null
						}else if (FindType.NOT_EQUAL_.equals(columnNamePrefix)) {
							sql.append(" AND "+columnName+" <> ?");//不等于
						}else if (FindType.NOT_IN_.equals(columnNamePrefix)) {//解决 jdbc bug in 不用 ？  处理
							sql.append(" AND "+columnName+" NOT IN( "+e.getValue()+" )");
							flag_add_value = false;
						}else if (FindType.MORE_.equals(columnNamePrefix)) {
							sql.append(" AND "+columnName+" > ?");
						}else if (FindType.LESS_.equals(columnNamePrefix)) {
							sql.append(" AND "+columnName+" < ?");
						}else if (FindType.MORE_EQUAL_.equals(columnNamePrefix)) {
							sql.append(" AND "+columnName+" >= ?");
						}else if (FindType.LESS_EQUAL_.equals(columnNamePrefix)) {
							sql.append(" AND "+columnName+" <= ?"); //小于等于
						}
					} else if(e.getKey().contains(OR_FLAG)){ //是否为 or 的分组查询 默认的 = 
							String groupName = StringUtils.split(e.getKey(),OR_FLAG)[0];
							String cName =   StringUtils.split(e.getKey(),OR_FLAG)[1]; // 真实的字段名
							String sourceValue = ""; // 该分组是否存在 原有值
							if(findOR.containsKey(groupName)){
								sourceValue = findOR.get(groupName);
							}
							findOR.put(groupName, sourceValue+(sourceValue.length()>0?",":"")+cName+"="+e.getValue());
							flag_add_value = false; // 不需要添加查询值
					}else if(e.getKey().contains(LIKE_OR_FLAG)){ //是否为 or 的分组查询  支持 like
 						String groupName = StringUtils.split(e.getKey(),LIKE_OR_FLAG)[0];
						String cName =   StringUtils.split(e.getKey(),LIKE_OR_FLAG)[1]; // 真实的字段名
						String sourceValue = ""; // 该分组是否存在 原有值
						if(findORLike.containsKey(groupName)){
							sourceValue = findORLike.get(groupName);
						}
						findORLike.put(groupName, sourceValue + (sourceValue.length() > 0 ? "^" : "") + cName + "="+e.getValue());
						flag_add_value = false; // 不需要添加查询值
					} else { // 默认为 等号
						columnName = e.getKey();
						sql.append(" AND "+columnName+" =?");
					} 
					
					if (flag_add_value) { //  是否初始化
						param = param==null?new ArrayList<Object>():param;
						if (FindType.ALL.equals(flag_like)){ // 是否为 like 查询
							param.add("%"+e.getValue()+"%");  
						} else if (FindType.LEFT.equals(flag_like)){ //  左 like 查询
							param.add("%"+e.getValue());  
						} else if (FindType.RIGHT.equals(flag_like)){ // 右 like 查询
							param.add(e.getValue() + "%");  
						} else {
							param.add(e.getValue()); // 参数对应的值
						}
					}
				}
			}
			if(findOR.size()>0){ //  需要解析 or 分组查询 (支持不同 字段名称 的 or 分组查询)
				for (Map.Entry<String, String> e:findOR.entrySet()) {
					 String valueString = e.getValue();
					 String [] currentGroup = StringUtils.split(valueString,",");
					 sql.append(" AND ( "); //  分组的开始
					 for (int i = 0; i < currentGroup.length; i++) { //  是否包含多个值
						if(currentGroup[i]!=null && currentGroup[i].length()>0){
							if(i>0)sql.append(" OR ");
							sql.append(StringUtils.split(currentGroup[i],"=")[0]+" = ? ");	
							param.add(StringUtils.split(currentGroup[i],"=")[1]);
						}
					 }
					 sql.append(" ) "); // 分组的结束
				}
			}
			if(findORLike.size()>0){ //  需要解析 or 分组查询 (支持不同 字段名称 的 or 分组查询)
				for (Map.Entry<String, String> e:findORLike.entrySet()) {
					String valueString = e.getValue();
					String [] currentGroup = StringUtils.split(valueString,"^");
					sql.append(" AND ( "); //  分组的开始
					for (int i = 0; i < currentGroup.length; i++) { //  是否包含多个值
						if(currentGroup[i]!=null && currentGroup[i].length()>0){
							if(i>0)sql.append(" OR ");
							sql.append(StringUtils.split(currentGroup[i],"=")[0]+" LIKE ?");	
							param.add("%"+StringUtils.split(currentGroup[i],"=")[1]+"%");
						}
					}
					sql.append(" ) "); // 分组的结束
				}
			}
			//---释放资源----
			findOR.clear();
			findORLike.clear();
			if(pattern.matcher(sql.toString()).find()){
				log.error("请求参数包含非法参数--------------------------");
				throw new RuntimeException("非法参数"+sql.toString());
			}
		} catch (Exception e) {
			log.error("解析sql 语句 出错", e);
		}
		return sql.toString();

	}
	
	/**检测是否包含SQL 特殊字符
	 * @param str
	 */
	public static void isRisk(String str) {
		if(pattern.matcher(str).find()){
			log.error("请求参数包含非法参数--------------------------");
			throw new RuntimeException("非法参数"+str);
		}
	}
}
